package org.example.controller;


import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.ReflectUtil;
import org.example.exception.BizException;
import org.example.util.SSEUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.http.MediaType;
import org.springframework.http.StreamingHttpOutputMessage;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;

@Controller
public class ParseHtmlController {


	//	@PostMapping("/get")
	public String parseHtml(@RequestParam("fileWorkTime") MultipartFile file, Model model) {
		if (Objects.isNull(file) || file.getSize() == 0) {
			throw new BizException("文件为空");
		}
		if (file.getSize() / 1024 / 1204 > 5) {
			throw new BizException("文件过大");
		}
		Document doc = null;
		try {
			doc = Jsoup.parse(file.getInputStream(), "UTF-8", "http://localhost");
		} catch (IOException e) {
			throw new BizException(e.getMessage());
		}
		Iterator<Element> iterator = doc.select("span[id*=staff_list_lblDKTime]").iterator();
		int totalMinutes = 0;
		int totalDay = 0;
		while (iterator.hasNext()) {
			Element next = iterator.next();
			Pattern pattern = Pattern.compile("(\\d+)小时(\\d+)分");
			Matcher matcher = pattern.matcher(next.text());
			if (matcher.find()) {
				int hours = Integer.parseInt(matcher.group(1));
				String dateType = next.parent().nextElementSibling().selectFirst("span[id*=gvKQYCSQ_staff_list_YCLX]").text();
				if (hours >= 8 && ("考勤正常").equals(dateType)) {
					int minutes = Integer.parseInt(matcher.group(2));
					totalMinutes += hours * 60 + minutes - 30;
					totalDay++;
				}
			}
		}
		BigDecimal hours = new BigDecimal(totalMinutes).divide(new BigDecimal(60), 3, RoundingMode.UP);
		BigDecimal result = hours
				.divide(new BigDecimal(totalDay), 3, RoundingMode.UP);
		model.addAttribute("result", String.format("本月总时长：%s小时", hours));
		model.addAttribute("result2", String.format("本月有效出勤天数：%s天", totalDay));
		model.addAttribute("result3", String.format("本月平均工时：%s小时", result));
		return "workTime";
	}

	public int calculateWorkdaysInMonth(int year, int month) {
		LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
		LocalDate lastDayOfMonth = firstDayOfMonth.with(TemporalAdjusters.lastDayOfMonth());
		int workdays = 0;

		for (LocalDate date = firstDayOfMonth; !date.isAfter(lastDayOfMonth); date = date.plusDays(1)) {
			DayOfWeek dayOfWeek = date.getDayOfWeek();
			if (dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY) {
				workdays++;
			}
		}
		return workdays;
	}


	@GetMapping(value = "/sub", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
	public SseEmitter subscribe() {
		// 添加订阅,建立sse链接
		SseEmitter emitter = SSEUtils.addSub("123");
		List<String> list = List.of("世", "界", "上", "最", "重", "要", "的", "事", "情", "是", "吃", "饭");
		new Thread(() -> {
			try {
				for (int i = 0; i < list.size(); i++) {
					// 发送消息
					SSEUtils.pubMsg("123", "", String.valueOf(i), list.get(i));
					Thread.sleep(300);
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				// 消息发送完关闭订阅
				SSEUtils.closeSub("123");
			}
		}).start();
		return emitter;
	}

	@PostMapping("/get")
	public String parseHtml2(@RequestParam("fileWorkTime") MultipartFile file, Model model) {
		if (Objects.isNull(file) || file.getSize() == 0) {
			throw new BizException("文件为空");
		}
		if (file.getSize() / 1024 / 1204 > 5) {
			throw new BizException("文件过大");
		}
		Document doc = null;
		try {
			doc = Jsoup.parse(file.getInputStream(), "UTF-8", "http://localhost");
		} catch (IOException e) {
			throw new BizException(e.getMessage());
		}
		Iterator<Element> iterator = doc.select("span[id*=staff_list_WorkingStar]").iterator();
		int totalMinutes = 0;
		int totalDay = 0;
		while (iterator.hasNext()) {
			Element next = iterator.next();
			String startTime = next.text();
			if ("无".equals(startTime)) {
				continue;
			}
			String startId = next.attributes().get("id");
			String abnormalType = doc.selectFirst("span[id=" + startId.replace("WorkingStar", "AbnormalClassification") + "]").text();
			if (abnormalType.contains("QJSQ")) {
				continue;
			}
			String endTime = doc.selectFirst("span[id=" + startId.replace("WorkingStar", "WorkingEnd") + "]").text();
			if ("无".equals(endTime)) {
				continue;
			}
			String dateType = doc.selectFirst("span[id=" + startId.replace("WorkingStar", "YCLX") + "]").text();
			String regexStr = "(\\d+):(\\d+)";
			int startHours = Integer.parseInt(ReUtil.get(regexStr, startTime, 1));
			int startMinutes = Integer.parseInt(ReUtil.get(regexStr, startTime, 2));
			int endHours = Integer.parseInt(ReUtil.get(regexStr, endTime, 1));
			int endMinutes = Integer.parseInt(ReUtil.get(regexStr, endTime, 2));
			totalMinutes += (endHours - startHours) * 60 + (endMinutes - startMinutes) - 90;
			if ("考勤正常".equals(dateType)) {
				totalDay++;
			}
		}
		BigDecimal hours = new BigDecimal(totalMinutes).divide(new BigDecimal(60), 3, RoundingMode.UP);
		BigDecimal result = hours
				.divide(new BigDecimal(totalDay), 3, RoundingMode.UP);
		model.addAttribute("result", String.format("本月总时长：%s小时", hours));
		model.addAttribute("result2", String.format("本月有效出勤天数：%s天", totalDay));
		model.addAttribute("result3", String.format("本月平均工时：%s小时", result));
		int workDays = getRemainingWorkingDaysOfCurrentMonth();
		model.addAttribute("result4", String.format("本月剩余工作日：%s天", workDays));
		BigDecimal workHours = BigDecimal.valueOf(totalDay + workDays).multiply(BigDecimal.valueOf(8.5)).
				subtract(hours).divide(BigDecimal.valueOf(workDays), 3, RoundingMode.UP);
		model.addAttribute("result5", String.format("预期工作时长：%s小时", workHours));
		if (workHours.compareTo(BigDecimal.valueOf(7.5d)) < 0) {
			model.addAttribute("result6", "恭喜你，荣获卷王称号，实现下班自由");
			model.addAttribute("juanWang", true);
		}
		return "workTime";
	}

	public static int getRemainingWorkingDaysOfCurrentMonth() {
		LocalDate today = LocalDate.now();
		LocalDate lastDayOfMonth = today.withDayOfMonth(today.lengthOfMonth());

		return (int) IntStream.rangeClosed(today.getDayOfMonth(), lastDayOfMonth.getDayOfMonth())
				.mapToObj(today::withDayOfMonth)
				.filter(ParseHtmlController::isWeekday)
				.count();
	}

	private static boolean isWeekday(LocalDate date) {
		DayOfWeek dayOfWeek = date.getDayOfWeek();
		return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;
	}
}
